Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default to first non-disabled option for select elements #10456

Merged
merged 4 commits into from Sep 1, 2017

Conversation

aweary
Copy link
Contributor

@aweary aweary commented Aug 14, 2017

This fixes a regression that @nhunzaker found in #10142 where select elements were defaulting to the first option, regardless of whether it was disabled or not. This was not the behavior in 15.6. Copying my comment on this from Nate's PR:

This issue stems from #8349 which introduced an updateOptions call when a select element is mounted. IfupdateOptions doesn't find a matching option it defaults to setting the first option as selected.

In previous versions updateOptions was not called on the initial mount, so it defaulted to the standard behavior of the browser.

This brings us back in sync with the HTML spec which states:

If the select element's display size is 1, and no option elements in the select element's list of options have their selectedness set to true, set the selectedness of the first option element in the list of options in tree order that is not disabled, if any, to true.

https://html.spec.whatwg.org/multipage/form-elements.html#the-select-element

@nhunzaker I can just cherry-pick the DOM fixtures from #10142 as part of this PR if you'd like!

Brandon Dail added 2 commits August 14, 2017 12:49
Instead of defaulting to the first option for a select element, which could be a disabled option, we find the first non-disabled option available while we looping through the options. If no option matches, set the first non-disabled option as selected.
if (options.length) {
options[0].selected = true;
if (defaultSelected !== null) {
defaultSelected.selected = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you didn't write all this, but the logic is hard to follow here...can we switch early to see if it's controlled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's a little dense, can you clarify what you mean by switching early to see if it's controlled? As far as I can tell, updateOptions only branches on multiple and doesn't really care if it's controlled or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking check if propValue was set, but that wouldn't actually work...I guess i don't have any specific suggestions :P but I felt like I had to read this through 3 times to understand it, and it feels like it should be easier to express

@sebmarkbage
Copy link
Collaborator

What happens to browser features like attempts to automatically restoring state and auto-fill? Does it care?

@nhunzaker
Copy link
Contributor

@aweary 🍒 ⛏ away.

@nhunzaker
Copy link
Contributor

@sebmarkbage We don't have fixture coverage for restored state and auto-fill. This would be a good addition to the suite. I'll write up an issue.

@@ -101,14 +101,18 @@ function updateOptions(
// Do not set `select.value` as exact behavior isn't consistent across all
// browsers for all cases.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish I knew what wasn't consistent -- and where? Like was it IE8?. I'll write up an issue to do some archaeology here.

Totally unrelated to this PR 😛.

@aweary aweary force-pushed the fix-select-default-value-regression branch from f30b9b8 to f2dea9d Compare August 30, 2017 17:26
@gaearon
Copy link
Collaborator

gaearon commented Sep 1, 2017

What is the status on this?

@aweary
Copy link
Contributor Author

aweary commented Sep 1, 2017

@gaearon I cherry-picked the test fixtures, so it should be good. Feel free to merge if it looks good to you.

@gaearon
Copy link
Collaborator

gaearon commented Sep 1, 2017

The fixture is broken for me.
There's a few consts before imports (probably because react-scripts version has changed since).

But I also get a runtime error:

screen shot 2017-09-01 at 1 14 51 pm

Inside selects/index.js, _nestedDOMNode is always null so _renderNestedSelect fails.

@gaearon gaearon added this to the 16.0 milestone Sep 1, 2017
<span className="hint" />
</fieldset>
<fieldset>
<legend>Controlled in nested subtree</legend>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this case removed intentionally?

@gaearon gaearon merged commit 80411ea into facebook:master Sep 1, 2017
@gaearon
Copy link
Collaborator

gaearon commented Sep 1, 2017

Thanks!

@aweary
Copy link
Contributor Author

aweary commented Sep 1, 2017

Thanks for the fix @gaearon!

@bvaughn bvaughn mentioned this pull request Sep 7, 2017
flarnie pushed a commit to flarnie/react that referenced this pull request Sep 8, 2017
)

* Default to first non-disabled option for select

Instead of defaulting to the first option for a select element, which could be a disabled option, we find the first non-disabled option available while we looping through the options. If no option matches, set the first non-disabled option as selected.

* Add ReactDOMSelect test for defaulting to non-disabled options

* Add test fixtures to cover disabled selected options

* Fix bad merge
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants